home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 139_01.zip / KED2.C < prev    next >
Text File  |  1993-06-03  |  24KB  |  707 lines

  1. /*
  2. TITLE:        Karel The Robot;
  3. VERSION:    1.0;
  4. DATE:        09/27/1984;
  5. DESCRIPTION:
  6.     "Part 2 of source code for syntax-directed editor,
  7.      KED. Other functions.";
  8. KEYWORDS:    Editor, syntax;
  9. SYSTEM:        CP/M 2+;
  10. FILENAME:    KED2.C
  11. AUTHORS:    Linda Rising;
  12. COMPILERS:    BDS C;
  13. REFERENCES:
  14.     AUTHOR: Richard E. Pattis;
  15.     TITLE: "KAREL the Robot: A Gentle Introduction
  16.         to the Art of Programming";
  17.     CITATION: "";
  18. ENDREF
  19. */
  20.  
  21.  
  22. #include <bdscio.h>
  23. #include <ked.h>
  24.  
  25.  
  26. readin(w)   /* find location of command in comm array or symbol table */
  27. char w[];
  28. {
  29.           int c,i,l,m;
  30.  
  31.           do {
  32.             inputs(w);
  33.             if ((m = match(w,comm,MAXCOMM)) != NOMATCH)
  34.                return m;              
  35.             if (m == NOMATCH && last != first && p != pr) {
  36.                l = pr->lastin;
  37.                if (l == 15) 
  38.                    l = last;
  39.                for (i = first; i != l; i = new[i].nextin)
  40.                     if ((c = strcomp(w,new[i].defname)) == 0) 
  41.                        return ( -i - 1);
  42.             }          
  43.             printf("INVALID COMMAND. TYPE MN TO SEE MENU.\n?");
  44.           } while (m == NOMATCH);
  45. }
  46.  
  47.  
  48.  
  49. menu()           /* print updated menu */
  50. {
  51.           int i;
  52.  
  53.           printf("THE FOLLOWING IS A LIST OF VALID ");
  54.           printf("COMMANDS FOR THIS EDITOR.\n\n");
  55.           printf("  INSTRUCTIONS\n");   
  56.           printf("m          move\n");
  57.           printf("tl         turnleft\n");
  58.           printf("pi         pickbeeper\n");
  59.           printf("pu         putbeeper\n");
  60.           printf("to         turnoff\n");
  61.           printf("b          BEGIN\n");
  62.           printf("bx         BEGINNING-OF-EXECUTION\n");
  63.           printf("nd         END\n");
  64.           printf("ndc        end construct\n");
  65.           printf("ndx        END-OF-EXECUTION\n");
  66.           printf("if         IF\n");
  67.           printf("el         ELSE\n");
  68.           printf("it         ITERATE\n");
  69.           printf("wh         WHILE\n");
  70.           printf("df         DEFINE-NEW-INSTRUCTION\n");
  71.       printf("\nTYPE ANY KEY TO CONTINUE.\n");
  72.       getchar();
  73.           if (last != first) {   /* any valid sym tab entries? */
  74.            printf("\n  USER-DEFINED COMMANDS\n");
  75.            for (i = first; i != last; i = new[i].nextin)
  76.                 printf("%s\n", new[i].defname);  
  77.           }
  78.           printf("\n  EDIT COMMANDS\n");      
  79.           printf("n          move pointer to next instruction\n");
  80.           printf("nc         move pointer to next construct\n");
  81.           printf("n-         move pointer to previous instruction\n");
  82.           printf("n--        move pointer back 10 lines\n"); 
  83.           printf("d          delete current instruction\n");
  84.       printf("c          print current line\n");
  85.           printf("p          print next 20 lines\n");
  86.           printf("i          insert new instruction before current one\n");
  87.           printf("t          move pointer to the first line\n");
  88.           printf("l          list the rest of the program\n");
  89.           printf("s          save the program\n");
  90.           printf("mn         print an updated menu\n");
  91.           printf("q          quit the edit program\n");
  92.       printf("\nTYPE ANY KEY TO CONTINUE.\n");
  93.       getchar();
  94.           printf("\n  TESTS\n");
  95.           printf("n          facing-north\n");
  96.           printf("nn         not-facing-north\n");
  97.           printf("s          facing-south\n");
  98.           printf("ns         not-facing-south\n");
  99.           printf("e          facing-east\n");
  100.           printf("ne         not-facing-east\n");
  101.           printf("w          facing-west\n");
  102.           printf("nw         not-facing-west\n");
  103.           printf("c          next-to-a-beeper (beeper on corner)\n");
  104.           printf("nc         not-next-to-a-beeper\n");
  105.           printf("b          any-beepers-in-beeper-bag\n");
  106.           printf("nb         no-beepers-in-beeper bag\n");
  107.           printf("f          front-is-clear\n");
  108.           printf("nf         front-is-blocked\n");
  109.           printf("l          left-is-clear\n");
  110.           printf("nl         left-is-blocked\n");
  111.           printf("r          right-is-clear\n");
  112.           printf("nr         right-is-blocked\n");
  113. }
  114.  
  115. createtree()                      /* reads information from old file1 */
  116. {
  117.            int i,in,d,fn,fs,b,t,l;
  118.            struct tnode *alloc();
  119.  
  120.            fscanf(ibuf1, "%d %d %d %d %d %d %d %d",
  121.                   &i,&in,&d,&fn,&fs,&b,&t,&l);
  122.            pr = NULL;
  123.            p = alloc(24);                 
  124.            tree(i,in,d,fn,fs,b,t,l);              /* store first node */
  125.            root = p;
  126.            p = root->sub = alloc(24);
  127.            pr = root;
  128.            fscanf(ibuf1, "%d %d %d %d %d %d %d %d",
  129.                   &i,&in,&d,&fn,&fs,&b,&t,&l);
  130.            while (i != NDX && i != CPMEOF && i != EOF) { 
  131.                createnode(ibuf1,i,in,d,fn,fs,b,t,l);    
  132.                fscanf(ibuf1, "%d %d %d %d %d %d %d %d",
  133.                       &i,&in,&d,&fn,&fs,&b,&t,&l);
  134.            }
  135.            endcons();
  136.            tree(i,in,d,fn,fs,b,t,l);
  137.            pr = p;
  138.            fclose(ibuf1);        
  139. }
  140.  
  141.  
  142. createnode(ibuf1,i,in,d,fn,fs,b,t,l)    /* restores nodes for parse tree */
  143. FILE *ibuf1;
  144. int i,in,d,fn,fs,b,t,l;
  145. {
  146.           int j;
  147.           char w[MAXLINE];
  148.           struct tnode *allocp();
  149.  
  150.           if (d == NEWINSTR && pr->instr != DEF) {
  151.               i = reloc[i];                   /* set up array to convert */
  152.               j = 0;                              /* old symb tab to new */
  153.               while (new[i].loc[j] != NULL)
  154.                      j++;
  155.               new[i].loc[j] = p;
  156.               new [i].loc[++j] = NULL;
  157.           if (l != 15)
  158.          l = last;
  159.               tree(i,in,d,fn,fs,b,t,l);
  160.               p = p->next = allocp();
  161.           } else switch (i) { 
  162.                  case 0:            /* move */
  163.                  case 1:            /* turnleft */
  164.                  case 2:            /* pickbeeper */
  165.                  case 3:            /* putbeeper */
  166.                  case 4:            /* turnoff */
  167.                     while (in < pr->indent)
  168.                            endcons();
  169.             if (l != 15)
  170.                l = last;
  171.                     tree(i,in,d,fn,fs,b,t,l);
  172.                     p = p->next = allocp();
  173.                     break;
  174.                 case 5:             /* BEGIN */
  175.                 case 7:             /* BEGINNING-OF-EXECUTION */
  176.                 case 13:            /* ELSE */
  177.            if (l != 15)
  178.               l = last;
  179.                    tree(i,in,d,fn,fs,b,t,l);
  180.                    p = p->sub = allocp();
  181.                    break;
  182.                case 8:              /* END */
  183.           if (l != 15)
  184.              l = last;
  185.                   tree(i,in,d,fn,fs,b,t,l);
  186.                   p = p->next = allocp();
  187.                   endcons();
  188.                   break;
  189.                case 11:             /* IF */
  190.                   while (in < pr->indent)
  191.                       endcons();
  192.           if (l != 15)
  193.              l = last;
  194.                   tree(i,in,d,fn,fs,b,t,l);
  195.                   p = p->sub = allocp();
  196.                   fscanf(ibuf1,"%d %d %d %d %d %d %d %d",
  197.                          &i,&in,&d,&fn,&fs,&b,&t,&l);         /* get test */
  198.           if (l != 15)
  199.              l = last;
  200.                   tree(i,in,d,fn,fs,b,t,l);
  201.                   p = p->sub = allocp();
  202.                   fscanf(ibuf1, "%d %d %d %d %d %d %d %d",
  203.                          &i,&in,&d,&fn,&fs,&b,&t,&l);         /* get THEN */
  204.           if (l != 15)
  205.              l = last;
  206.                   tree(i,in,d,fn,fs,b,t,l);
  207.                   p = p->sub = allocp();
  208.                   break;
  209.                case 14:               /* ITERATE */
  210.                case 15:               /* WHILE */
  211.                   while (in < pr->indent)
  212.                       endcons();
  213.           if (l != 15)
  214.              l = last;
  215.                   tree(i,in,d,fn,fs,b,t,l);
  216.                   p = p->sub = allocp();
  217.                   fscanf(ibuf1,"%d %d %d %d %d %d %d %d",
  218.                          &i,&in,&d,&fn,&fs,&b,&t,&l);      /* get test or */
  219.           if (l != 15)                       /* pos int */
  220.              l = last;
  221.                   tree(i,in,d,fn,fs,b,t,l);                   
  222.                   p = p->sub = allocp();
  223.                   break;
  224.                case 16:             /* DEFINE-NEW-INSTRUCTION */
  225.                   tree(i,in,d,fn,fs,b,t,last);
  226.                   p = p->sub = allocp();
  227.                   fscanf(ibuf1,"%d %d %d %d %d %d %d %d",
  228.                          &i,&in,&d,&fn,&fs,&b,&t,&l);      /* get new name */
  229.                   i = reloc[i] = last;                        /* translate */
  230.                   j = 0;                              /* sym tab subscript */
  231.                   while ((w[j++] = getc(ibuf1)) != '\n')
  232.                       ;
  233.                   j -= 3;
  234.                   w[j] = '\0';
  235.                   strcpy(new[i].defname,w);
  236.                   new[i].nextin = last + 1; /* store next ref in sym table */
  237.                   tree(i,in,d,fn,fs,b,t,last);
  238.                   p = p->sub = allocp();
  239.                   break;
  240.                }
  241. }   
  242.  
  243.  
  244. insertinstr()     /* prepare to add instructions in insert mode */
  245. {
  246.     
  247.           struct tnode *allocp(), *conbegin();
  248.  
  249.           insert = 1;
  250.           insertnode = curr;
  251.           if ((curr->instr == NDX ||        /* find previous construct */
  252.                curr->instr == ND) && curr->del !=  NEWINSTR) {
  253.           p = curr->prev;
  254.           if (p->cons != 1)
  255.                  while (p->indent > curr->indent + 1)
  256.                      p = conbegin(p);
  257.           } else p = curr->prec;
  258.       if (p->instr == IFF) {     /* set THEN as start of construct */
  259.          p = advance(p);                /* so ELSE can be inserted */
  260.          p = advance(p);
  261.       }
  262.       ins = p->indent;       /* final indent level for construct */
  263.       if ((p->instr == BX || p->instr == BEG || p->instr == BEPGM)
  264.            && p->del != NEWINSTR)
  265.            ++ins;
  266.           if (insertnode == p->sub ||
  267.           (p->instr == BX && p->del != NEWINSTR)) 
  268.               p = p->sub = allocp();           /* set up links to next */
  269.           else {                                   /* node to be added */
  270.                p = p->next = allocp();
  271.            temp = insertnode->prev;  
  272.                temp->next = p;
  273.           }
  274. }
  275.  
  276.  
  277. endinsert()        /* exit insert mode */
  278. {
  279.           if (insert) {
  280.               if (pr->instr == THEN) 
  281.          if (p == pr->sub)
  282.             printf("PLEASE COMPLETE CONSTRUCT\n");
  283.              else endcons();
  284.               if (pr->indent > ins)
  285.                  printf("PLEASE COMPLETE CONSTRUCT\n");
  286.               else {
  287.                  insert = 0;
  288.                  insertnode->prec = pr;
  289.                  if (tempend != NULL) {            /* if a node has been */
  290.                      tempend->next = insertnode;   /* inserted link last */
  291.                      insertnode->prev = tempend;          /* instruction */
  292.                      tempend = NULL;
  293.                  } else if (temp != NULL)           /* otherwise restore */
  294.                             temp->next = insertnode;        /* old links */
  295.                         else if (p == pr->next)
  296.                                  pr->next = insertnode;
  297.                              else pr->sub = insertnode;
  298.                  temp = NULL;  
  299.                  free(p);
  300.                  p = pr;
  301.          curr = insertnode;
  302.               }
  303.          }
  304.  
  305.  
  306. delete()                /* delete or replace current instruction */
  307. {
  308.           int c;
  309.  
  310.           switch(curr->del) {
  311.           case 0:       /* reserved word */
  312.              printf("DELETE ENTIRE CONSTRUCT? (Y/N)\n");
  313.              if ((c = toupper(getchar())) == 'Y')
  314.                   deletecon();
  315.              else printf("\n");
  316.              break;
  317.           case 1:       /* simple instruction */
  318.              dealloc(curr,curr->next);
  319.              break;
  320.           case 2:       /* test */
  321.              prompt("TYPE REPLACEMENT ",1,"",5,0);
  322.              curr->instr = getest();
  323.              print(curr->prev,CONSOLE);
  324.              print(curr,CONSOLE);
  325.              break;
  326.           case 3:       /* positive number */
  327.              prompt("TYPE REPLACEMENT ",2,"",16,0);
  328.              curr->instr = getint();
  329.              print(curr->prev,CONSOLE);
  330.              print(curr,CONSOLE); 
  331.              break;
  332.           case 4:       /* new name */
  333.              if (curr->prev->instr == DEF) {
  334.                  prompt("TYPE REPLACEMENT ",4,"",9,0);
  335.                  getnew(curr->instr);
  336.                  print(curr->prev,CONSOLE);
  337.                  print(curr,CONSOLE); 
  338.              } else dealloc(curr,curr->next);
  339.              break;
  340.           case 5:       /* BEGINNING-OF-PROGRAM, BX, NDX */
  341.              printf("CAN'T BE DELETED\n?");
  342.              break;
  343.       }
  344. }
  345.  
  346.  
  347. deletecon()       /* locate start and end of current construct */
  348. {
  349.  
  350.           struct tnode *ptr1, *ptr2, *conbegin(), *conend();
  351.  
  352.           if (curr->instr == THEN || curr->cons != 1)
  353.               ptr1 = conbegin(curr);       /* locate start of construct */
  354.           else ptr1 = curr; 
  355.           if (ptr1->instr == DEF)          /* delete all references for */
  356.               deletenewin(ptr1->sub->instr);           /* defined instr */
  357.           ptr2 = conend(ptr1);               /* locate end of construct */
  358.           dealloc(ptr1,ptr2);
  359. }
  360.  
  361.  
  362. struct tnode *conbegin(ptr)       /* locates start of current construct */
  363. struct tnode *ptr;
  364. {
  365.           int in;
  366.  
  367.           if (ptr->instr == ND && ptr->del != NEWINSTR) {
  368.               in = ptr->indent;
  369.               while ((ptr = ptr->prev)->indent > in)
  370.                        ;
  371.           }
  372.           while ((ptr = ptr->prev)->cons != 1 || ptr->instr == THEN)
  373.              ;   
  374.           return ptr;
  375. }
  376.  
  377.  
  378. struct tnode *conend(ptr)        /* locates end of current construct */
  379. struct tnode *ptr;
  380. {
  381.  
  382.           int d,in;
  383.           struct tnode *advance();
  384.  
  385.           in = ptr->indent;
  386.       if (ptr != endof)
  387.              ptr = advance(ptr);
  388.           while (ptr != endof && (ptr->indent > in ||
  389.                  (d = ptr->del) == TEST || d == POSINT || d == NEWINSTR)) 
  390.               ptr = advance(ptr);
  391.           if (ptr == endof && (ptr->indent > in ||
  392.               (d = ptr->del) == TEST || d == POSINT || d == NEWINSTR))
  393.               ptr = p;
  394.           return ptr; 
  395.  
  396. }
  397.  
  398.  
  399. deletenewin(i)                /* removes user-defined instruction */
  400. int i;
  401. {
  402.  
  403.           int j;
  404.           struct tnode *ptr;
  405.  
  406.           j = 0;
  407.           while ((ptr = new[i].loc[j]) != NULL) { 
  408.               dealloc(ptr,ptr->next);        /* locate and delete */
  409.               j++;                                 /* uses in pgm */
  410.           }
  411.           j = first;
  412.           if (j != i) {
  413.              while (new[j].nextin != i)             /* remove sym */
  414.                  j = new[j].nextin ;          /* table references */
  415.              new[j].nextin = new[i].nextin;
  416.           } else if (new[first].nextin == last)
  417.                      --last;
  418.                  else first = new[i].nextin;
  419. }
  420.  
  421.  
  422.  
  423. dealloc(ptr1,ptr2)                 /* free space from ptr1 up to ptr2 */
  424. struct tnode *ptr1,*ptr2;
  425. {
  426.  
  427.           struct tnode *ptr;
  428.       
  429.           printf("\n");
  430.           if (ptr2->instr != NDX || ptr2->del == NEWINSTR)
  431.               ptr2->prec = ptr1->prec;        /* set up links between */
  432.           curr = ptr2;                        /* ptr2 & ptr1's parent */
  433.           ptr = ptr2->prev = ptr1->prev;
  434.           if (ptr1 == ptr->sub &&
  435.          (ptr2->instr != NDX || ptr2->del == NEWINSTR))
  436.               ptr->sub = ptr2;
  437.           else { 
  438.              ptr->next = ptr2;
  439.              if (ptr2->instr == NDX && ptr2->del != NEWINSTR)
  440.                  ptr->sub = NULL;
  441.           }
  442.           while (ptr1 != ptr2) {               /* deallocate nodes in */
  443.               ptr = ptr1;                     /* succession and print */
  444.               if (ptr1->sub != NULL)
  445.                   ptr1 = ptr1->sub;
  446.               else if (ptr1->next != NULL)
  447.                        ptr1 = ptr1->next;
  448.               print(ptr,CONSOLE);
  449.               free(ptr);  
  450.           }
  451.           if (ptr2 == p && p != pr) {              /* if last line of */
  452.               endof = temp = curr = ptr1->prev;   /* pgm, set new eof */ 
  453.               pr = ptr1->prec;
  454.               temp->next = p;
  455.           }       
  456. }
  457.  
  458.  
  459. putintable(i)     /* add new name to symbol table */
  460. int i;
  461. {
  462.           int j,k;
  463.  
  464.           if (insert && insertnode->instr == DEF) {
  465.               j = insertnode->sub->instr;         /* if inserting before */
  466.               new[i].nextin = j;                    /* DEF locate proper */
  467.               for (k = first; new[k].nextin != last;)     /* position in */
  468.                    k = new[k].nextin;                     /* linked list */
  469.               new[k].nextin = last + 1;
  470.               if (j == first)
  471.                   first = i;
  472.               else {
  473.                  for (k = first; new[k].nextin != j;)
  474.                       k = new[k].nextin;
  475.                  new[k].nextin = i;
  476.              }                            /* otherwise add as last entry */
  477.           } else new[i].nextin = last + 1;
  478. }   
  479.  
  480.  
  481. savetree(p,argv)         /* write parse tree to file1, text to file2 */
  482. struct tnode *p;
  483. char **argv;
  484. {
  485.           struct tnode *advance(); 
  486.  
  487.           fcreat(argv[1],ibuf1);         /* open both files */  
  488.           fcreat(argv[2],ibuf2);         /* for writing */
  489.           while (p != endof) {
  490.               fprintf(ibuf1, "%d %d %d %d %d %d %d %d \n",   /*codes */
  491.                     p->instr,p->indent,p->del,p->nfollow,/* in file1 */
  492.                     p->sfollow,p->comp,p->cons,p->lastin);
  493.               print(p,ibuf2);                       /* text in file2 */
  494.               if (p->instr == DEF && p->del == 0) {
  495.                   p = advance(p);
  496.                   fprintf(ibuf1,"%d %d %d %d %d %d %d %d \n",
  497.                           p->instr,p->indent,p->del,p->nfollow,
  498.                           p->sfollow,p->comp,p->cons,p->lastin);
  499.                   print(p,ibuf2);
  500.                   fprintf(ibuf1,"%s \n",new[p->instr].defname);
  501.               }             
  502.               p = advance(p);      
  503.            } 
  504.            fprintf(ibuf1, "%d %d %d %d %d %d %d %d \n",
  505.                    9,1,5,4,4,0,2,10);
  506.            print(p,ibuf2);
  507.            putc(CPMEOF,ibuf1);    putc(CPMEOF,ibuf2);
  508.            fclose(ibuf1);         fclose(ibuf2);
  509.          
  510. }
  511.  
  512.  
  513.  
  514. tree(i,in,d,fn,fs,b,t,l)    /* store instruction codes in parse tree */
  515. int i,in,d,fn,fs,b,t,l;
  516. {
  517.          p->sub = NULL;
  518.          p->next = NULL;
  519.          p->prec = pr;
  520.          if (pr->sub != NULL && p == pr->next) {
  521.              p->prev = temp;                       /* set up link to */
  522.              temp = NULL;                    /* previous instruction */
  523.          } else p->prev = pr;
  524.          p->instr = i;
  525.          p->indent = in;
  526.          p->del = d;
  527.          p->nfollow = fn;
  528.          p->sfollow = fs;
  529.          p->comp = b;
  530.          p->cons = t;
  531.          p->lastin = l;
  532.          if (insert)
  533.              tempend = p;     /* last node inserted */
  534.          else endof = p;      /* last node added (eof) */
  535. }
  536.  
  537.  
  538. struct tnode *allocp()      /* get space for next node */
  539. {
  540.           struct tnode *alloc(), *ptr;
  541.  
  542.           ptr = alloc(24);
  543.           curr = p;
  544.           pr = p;
  545.           return ptr;
  546. }
  547.  
  548.  
  549. inputs(w)         /* read in next command */
  550. char w[];
  551. {
  552.           int i,m;
  553.       char c;
  554.  
  555.       m = 0;
  556.           i = 0;
  557.           while ((c = w[i++] = tolower(getchar())) != '\n')
  558.               if ((c > 'z' || c < 'a') && (c > '9' || c < '0') && c != '-') 
  559.         m = ERROR;
  560.           w[--i] = '\0';
  561.       return m;
  562. }
  563.  
  564.  
  565. match(w,s,max)          /* compares string to array element */
  566. char w[], *s[];
  567. int max;
  568. {
  569.           int c,i;
  570.  
  571.           for (i = 0; i < max; i++) {
  572.             c = strcomp(w,s[i]);
  573.             if (c == 0)                 /* if match, return */
  574.                 return i;                /* array subscript */
  575.           }
  576.           return NOMATCH;            /* else return NOMATCH */
  577. }
  578.  
  579.  
  580. prompt(mess1,num1,mess2,num2,i)       /* prompt for next instruction */
  581. char *mess1,*mess2;
  582. int num1, num2,i;
  583. {
  584.           int j;
  585.  
  586.           printf("%s",mess1);                  /* print first string */
  587.           switch(num1) {           /* print desired instruction type */  
  588.           case 1:
  589.              printf("<test>");
  590.              break;
  591.           case 2:
  592.              printf("<positive-number>");
  593.              break;
  594.           case 3:
  595.              for (j = 0; j < curr->indent;
  596.                          printf("  "), j++);
  597.          if (i == ND || i == NDC) {
  598.         printf("\b");
  599.         printf("\b");
  600.          }
  601.              printf("<instruction>");
  602.              break;
  603.           case 4:
  604.              printf("<new-name>");
  605.              break;
  606.           }
  607.           printf("%s",mess2);            /* print second string */
  608.           for (; num2-- > 0; printf("\b"))
  609.             ;
  610. }
  611.  
  612.  
  613. struct tnode *advance(ptr)         /* point to next line or eof */
  614. struct tnode *ptr;
  615. {
  616.           if (ptr->sub != NULL)
  617.               ptr = ptr->sub;
  618.           else if (ptr->next != NULL)
  619.                    ptr = ptr->next;
  620.           return ptr;
  621. }
  622.  
  623.  
  624. checkin(valid)   /* correct location for an instruction? */
  625. int *valid;
  626. {
  627.           int in;
  628.  
  629.           *valid = 1;
  630.           if (p == pr && !insert) {  /* if NDX added, must insert */
  631.               printf("INSERT ONLY\n?");
  632.               *valid = 0;
  633.           } else { 
  634.                if (pr->instr == THEN && p!= pr->sub) {
  635.                    endcons();               /* end THEN construct */
  636.            if (insert)            /* since ELSE not added */
  637.               ins = pr->indent;
  638.            }
  639.                if (pr->nfollow == 0 &&           
  640.                           p == pr->next)
  641.                    in = pr->indent;         
  642.                else if (pr->sfollow == 0 && 
  643.                                p == pr->sub)
  644.                         in = pr->indent + 1;
  645.                      else { 
  646.                         *valid = 0;
  647.                         printf("BAD LOCATION FOR COMMAND. ");
  648.                         printf("TYPE MN TO SEE MENU.\n?");
  649.                      }
  650.             }           
  651.           return in;
  652. }
  653.  
  654.  
  655. checkcomp(valid)         /* compound statement? */
  656. int *valid;
  657. {
  658.           int b;
  659.  
  660.           if (pr->comp == 2) {       /* if 2nd instr added without BEGIN */
  661.               *valid = 0;
  662.               printf("STRUCTURE NOT A COMPOUND STATEMENT\n?");
  663.           } else if (pr->comp == 1)  /* if 1st instr added without BEGIN */
  664.                      b = 2;            /* set warning for future entries */
  665.                  else b = pr->comp;
  666.           return b;
  667. }
  668.  
  669.  
  670.  
  671. endcons()         /* end construct */
  672. {  
  673.           int in;
  674.           struct tnode *alloc();
  675.   
  676.           if (pr->indent == 1)     /* only BX, NDX indented 1 level */
  677.               printf("LAST POSSIBLE LEVEL\n");   
  678.           else {
  679.              if (temp->next != p     /* keep last instr in previous */
  680.          || temp == NULL)               
  681.            temp = pr;            /* construct if NDC repeated */
  682.              do {
  683.               in = pr->indent;
  684.               while ((pr = pr->prev)->cons != 1 /* go back to start */
  685.                       || pr->indent >= in);         /* of construct */
  686.              } while (pr->instr == ELS);               /* skip ELSE */
  687.              if (pr->instr == DEF)          /* if DEF ended add new */
  688.                  last++;                         /* name to sym tab */
  689.              pr->next = alloc(24);
  690.              free(p);
  691.              p = temp->next = pr->next;
  692.           } 
  693. }    
  694.  
  695.  
  696. strcomp(s1,s2)
  697. char s1[],s2[];
  698. {
  699.       int i;
  700.  
  701.       i = 0;
  702.       while (s1[i] == s2[i])
  703.          if (s1[i++] == '\0' || i == 8)
  704.         return 0;
  705.       return s1[i] - s2[i];
  706. }